package  
{
	import net.flashpunk.Entity;
	import net.flashpunk.FP;
	import net.flashpunk.graphics.Tilemap;
	import net.flashpunk.masks.Grid;
	
	/**
	 * ...
	 * @author Edward Russell II
	 */
	public class Level extends Entity 
	{
		
		/**
		 * 
		 * @param	xml		source level
		 * @param	tileMap source level tile map
		 */
		public function Level(xml:Class, tileMap:Class) 
		{
			//call the loadMap() function
			loadMap(xml);
			
			//load the tiles and grid
			_tiles = new Tilemap(tileMap, _mapWidth, _mapHeight, 32, 32);	//these are the tiles that are displayed
			_grid = new Grid(_mapWidth, _mapHeight, 32, 32, 0, 0);			//these are the tiles that are used for collision data
			
			//set the level properties
			graphic = _tiles;
			mask = _grid;
			type = "level";
		}
		
		override public function added():void 
		{
			super.added();
			
			//after the level has been added to the world then build it
			buildWorld();
			
		}
		
		/**
		 * 
		 * @param	map	source map
		 */
		private function loadMap(map:Class):void
		{
			//set the local class variables
			_mapData		=	new XML(FP.getXML(map));			//set the local variable for map data to the passed class
			_mapScrolling	= 	int(_mapData.@scrolling);
			_mapHeight		=	int(_mapData.@height);
			_mapWidth		=	int(_mapData.@width);
			_cameraX		=	int(_mapData.camera.@x);
			_cameraY		=	int(_mapData.camera.@y);
			_cameraSpeed	=	int(_mapData.@cameraSpeed);
			GV.CURRENT_MAP	=	_mapData;
		}
		
		public function buildWorld():void
		{
			var tileList:XMLList;
			var dataElement:XML;
			
			//Here we iterate through the background list setting each tile
			tileList = _mapData.Background.tile;
			for each (dataElement in tileList) 
			{
				_tiles.setTile(int(dataElement.@x), int(dataElement.@y), int(dataElement.@id));
				this.layer = -1;
			}
			
			//Same as the above loop, but handling the foreground tiles
			tileList = _mapData.Solid.tile;
			for each (dataElement in tileList) 
			{
				_tiles.setTile(int(dataElement.@x), int(dataElement.@y), int(dataElement.@id));
				
				//here we set our grid for collision detection
				_grid.setTile(int(dataElement.@x), int(dataElement.@y));
				this.layer = -2;
			}
			
			//add the player(s) to the world
			tileList = _mapData.Entities.player_start;
			for each (dataElement in tileList){FP.world.add(new Player(int(dataElement.@x), int(dataElement.@y)));}
			
			//add all the enemies to the world
			tileList = _mapData.Entities.enemies;
			for each(dataElement in tileList){FP.world.add(new Enemy(dataElement.@id, int(dataElement.@x), int(dataElement.@y), Number(dataElement.@speed)));}
			
			//Lastly, if it's a scrolling map multiplay our bullet speed by our camera speed to keep them moving at the right speed
			if (_mapScrolling) GV.BULLET_SPEED = GV.BULLET_SPEED * _cameraSpeed;
			
		}
		
		override public function update():void 
		{
			//if it's a scrolling map call the scrollLevel() function, otherwise call the followPlayer() function
			if (_mapScrolling) scrollLevel();
			else if (!_mapScrolling) followPlayer();
			
			super.update();
		}
		
		private function scrollLevel():void
		{
			//if we haven't reached the end of the map...
			if (FP.camera.x + FP.width < _mapWidth) 
			{
				FP.camera.x += _cameraSpeed; //scroll the camera 
				for each (var e:Player in GV.PLAYER_LIST) e.x += _cameraSpeed; //scroll the player along with the camera
				
			}
			
		}
		
		public function followPlayer():void
		{
			//if the player is left of the bounding box
			if (GV.FIRST_PLAYER.x - FP.camera.x < _cameraOffset)
			{
				//and the map isn't at the beginning, move the camera back
				if (FP.camera.x > 0) FP.camera.x -= _cameraSpeed * (GC.PLAYER_SPEED / 100);
			}
			//if the player is over the right side of the camera bounding box
			else if ((FP.camera.x + FP.width) - (GV.FIRST_PLAYER.x + GV.FIRST_PLAYER.image.scaledWidth) < _cameraOffset)
			{
				//and the map isn't at the end, move the camera forward
				if (FP.camera.x + FP.width < _mapWidth) FP.camera.x += _cameraSpeed * (GC.PLAYER_SPEED / 100);
			}
			
			//Same as the code above, but handling the Y axis instead
			if (GV.FIRST_PLAYER.y - FP.camera.y < _cameraOffset)
			{
				if (FP.camera.y > 0) FP.camera.y -= _cameraSpeed * (GC.PLAYER_SPEED / 100);
			}
			else if ((FP.camera.y + FP.height) - (GV.FIRST_PLAYER.y + GV.FIRST_PLAYER.image.scaledHeight) < _cameraOffset)
			{
				if (FP.camera.y + FP.height < _mapHeight) FP.camera.y += _cameraSpeed * (GC.PLAYER_SPEED / 100);
			}
		}
		
		protected var _cameraOffset:int	= 200;
		protected var _cameraSpeed:int;
		
		protected var _mapData:XML;
		protected var _mapWidth:int = 6400;
		protected var _mapHeight:int = 480;
		protected var _cameraX:int = 0;
		protected var _cameraY:int;
		protected var _mapScrolling:int;
		
		protected var _grid:Grid;
		protected var _source:Class;
		protected var _tiles:Tilemap;
		
	}

}